package com.vinhvt.effiport.algorithm.genetic.bio;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


import com.vinhvt.effiport.algorithm.genetic.GAsParameters;
import com.vinhvt.effiport.util.Helper;


public class WeightChromosome implements IChromosome {
	
	private List<WeightGene> weightGene = new ArrayList<WeightGene>();

	public WeightChromosome() {};
	
	/**
	 * Instantiates a new weight chromosome.
	 * 
	 * @param bits the bits
	 */
	public WeightChromosome(boolean[] bits) {
		int wbl = GAsParameters.WEIGHT_BITS_LENGTH;
		int num = bits.length / wbl;	// number of genes
		
		for(int i = 0; i < num; i++) {
			boolean[] tmp = new boolean[wbl];
			for(int j = 0; j < wbl; j++) {
				tmp[j] = bits[i * wbl + j];
			}
			WeightGene wg = new WeightGene(tmp);
			this.weightGene.add(wg);			
		}
	}
	
	public void setADNStructure(boolean[] bits) {
		int wbl = GAsParameters.WEIGHT_BITS_LENGTH;
		int num = bits.length / wbl;	// number of genes
		
		for(int i = 0; i < num; i++) {
			boolean[] tmp = new boolean[wbl];
			for(int j = 0; j < wbl; j++) {
				tmp[j] = bits[i * wbl + j];
			}
			WeightGene wg = new WeightGene(tmp);
			this.weightGene.add(wg);			
		}
	}
	
	public void setWeightGene(List<WeightGene> geneWeight) {
		this.weightGene = geneWeight;
	}

	public List<WeightGene> getWeightGene() {
		return weightGene;
	}

	@Override
	public Gene getGene(int position) {
		return this.getWeightGene().get(position);
	}

	@Override
	public void addGene(Gene gene) {
		this.weightGene.add((WeightGene) gene);		
	}

	@Override
	public boolean[] getADNStructure() {
		boolean[] result = null;
		
		for(int i = 0; i < GAsParameters.INDIVIDUAL_SIZE; i++) {
			boolean[] next = this.getGene(i).getBits();
			result = Helper.extend(result, next);
		}
		
		return result;
	}

	@Override
	public void mutate() {
		double pm = GAsParameters.WPM;	
		
		boolean[] bits = this.getADNStructure();
		Random rand = new Random();
		for(int i = 0; i < bits.length; i++ ) {
			bits[i] = (rand.nextDouble() < pm) ? !bits[i] : bits[i] ;
		}
		this.setADNStructure(bits);
		
	}
	
	@Override
	public String toString() {
		String result = "";
		
		int size = GAsParameters.INDIVIDUAL_SIZE * GAsParameters.WEIGHT_BITS_LENGTH;
		for(int i = 0; i < GAsParameters.INDIVIDUAL_SIZE; i++) {
			result += this.weightGene.get(i).toString();
		}
		
		return result;
	}
}
